package com.example.web.sys_user.controller;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.jwt.JwtUtils;
import com.example.utils.ResultUtils;
import com.example.utils.ResultVo;
import com.example.web.sys_menu.entity.*;
import com.example.web.sys_menu.service.IMenuService;
import com.example.web.sys_user.entity.*;
import com.example.web.sys_user.service.IUserService;
import com.example.web.sys_user_role.entity.UserRole;
import com.example.web.sys_user_role.service.IUserRoleService;
import com.google.code.kaptcha.impl.DefaultKaptcha;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
import org.springframework.web.bind.annotation.*;
import sun.misc.BASE64Encoder;

import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.*;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author LS
 * @since 2024-02-20
 */
@Api(tags = "用户接口")
@RestController
@RequestMapping("/api/user")
public class UserController {

    @Resource
    private IUserService userService;
    @Resource
    private IUserRoleService userRoleService;
    @Resource
    private IMenuService menuService;
    @Autowired
    private DefaultKaptcha defaultKaptcha;
    @Autowired
    private JwtUtils jwtUtils;
    @Autowired
    private AuthenticationManager authenticationManager;
    @Autowired
    private PasswordEncoder passwordEncoder;

    @ApiOperation("新增")
    @PostMapping
    public ResultVo add(@RequestBody User user) {
        user.setPassword(passwordEncoder.encode(user.getPassword()));//密码加密
        user.setCreateTime(new Date());
        userService.saveUser(user);
        return ResultUtils.success("新增成功!");
    }

    @ApiOperation("编辑")
    @PutMapping
    public ResultVo edit(@RequestBody User user) {
        user.setUpdateTime(new Date());
        userService.editUser(user);
        return ResultUtils.success("编辑成功!");
    }

    @ApiOperation("删除")
    @DeleteMapping("/{userId}")
    public ResultVo delete(@PathVariable("userId") Long userId) {
        userService.deleteUser(userId);
        return ResultUtils.success("删除成功!");
    }

    @ApiOperation("列表")
    @GetMapping("/list")
    public ResultVo list(UserPage param) {
        //构造分页对象
        IPage<User> page = new Page<>(param.getCurrentPage(), param.getPageSize());
        //构造查询条件
        QueryWrapper<User> query = new QueryWrapper<>();
        if (StringUtils.isNotEmpty(param.getNickName())) {
            query.lambda().like(User::getNickName, param.getNickName());
        }
        if (StringUtils.isNotEmpty(param.getPhone())) {
            query.lambda().like(User::getPhone, param.getPhone());
        }
        query.lambda().orderByDesc(User::getCreateTime);//排序
        //查询列表
        IPage<User> list = userService.page(page, query);
        return ResultUtils.success("查询成功", list);
    }

    @ApiOperation("根据用户id查询用户的角色")
    @GetMapping("/getRoleList")
    public ResultVo getRoleList(Long userId) {
        QueryWrapper<UserRole> query = new QueryWrapper<>();
        query.lambda().eq(UserRole::getUserId, userId);
        List<UserRole> list = userRoleService.list(query);
        //角色id
        List<Long> roleList = new ArrayList<>();
        Optional.ofNullable(list).orElse(new ArrayList<>())
                .forEach(item -> roleList.add(item.getRoleId()));
        return ResultUtils.success("查询成功!", roleList);
    }

    @ApiOperation("重置密码")
    @PostMapping("/resetPassword")
    public ResultVo resetPassword(@RequestBody User user) {
        UpdateWrapper<User> query = new UpdateWrapper<>();
        query.lambda().eq(User::getUserId, user.getUserId())
                .set(User::getPassword, passwordEncoder.encode("123456"));
        if (userService.update(query)) {
            return ResultUtils.success("密码重置成功！");
        }
        return ResultUtils.error("密码重置失败！");
    }

    @ApiOperation("图片验证码")
    @PostMapping("/getImage")
    public ResultVo imageCode(HttpServletRequest request) {
        //获取session
        HttpSession session = request.getSession();
        //生成验证码
        String text = defaultKaptcha.createText();
        //存放到session
        session.setAttribute("code", text);
        //生成图片，转换为base64
        BufferedImage bufferedImage = defaultKaptcha.createImage(text);
        ByteArrayOutputStream outputStream = null;
        try {
            outputStream = new ByteArrayOutputStream();
            ImageIO.write(bufferedImage, "jpg", outputStream);
            BASE64Encoder encoder = new BASE64Encoder();
            String base64 = encoder.encode(outputStream.toByteArray());
            String captchaBase64 = "data:image/jpeg;base64," + base64.replaceAll("\r\n", "");
            return new ResultVo("生成成功", 200, captchaBase64);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (outputStream != null) {
                    outputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    @ApiOperation("登录")
    @PostMapping("/login")
    public ResultVo login(HttpServletRequest request, @RequestBody LoginParam param) {
        //获取前端传递过来的code
        String code = param.getCode();
        //获取session
        HttpSession session = request.getSession();
        //获取session里面的code
//        String code1 = (String) session.getAttribute("code");
//        if (StringUtils.isEmpty(code1)) {
//            return ResultUtils.error("验证码过期！");
//        }
//        //判断前端传递进来的code和session里面是否相等
//        if (!code1.equals(code)) {
//            return ResultUtils.error("验证码不正确！");
//        }
        //springSecurity加密之后的密码
        String password = passwordEncoder.encode(param.getPassword());
        //查询用户信息,交给springSecurity查询
        UsernamePasswordAuthenticationToken authenticationToken =
                new UsernamePasswordAuthenticationToken(param.getUsername(), param.getPassword());
        Authentication authenticate = authenticationManager.authenticate(authenticationToken);
        //交给springSecurity
        SecurityContextHolder.getContext().setAuthentication(authenticate);
        //获取用户信息
        User user = (User) authenticate.getPrincipal();
        //查询用户信息
//        QueryWrapper<User> query = new QueryWrapper<>();
//        query.lambda().eq(User::getUsername, param.getUsername())
//                .eq(User::getPassword, param.getPassword());
//        User one = userService.getOne(query);
//        if (one == null) {
//            return ResultUtils.error("用户名或密码不正确！");
//        }
        //返回用户信息和token
        LoginVo vo = new LoginVo();
        vo.setUserId(user.getUserId());
        vo.setNickName(user.getNickName());
        //生成token
        Map<String, String> map = new HashMap<>();
        map.put("userId", Long.toString(user.getUserId()));
        map.put("username", user.getUsername());
        String token = jwtUtils.generateToken(map);
        vo.setToken(token);
        return ResultUtils.success("登录成功！", vo);
    }

    @ApiOperation("查询菜单树")
    @GetMapping("/getAssignTree")
    public ResultVo getAssignTree(AssignTreeParam param) {
        AssignTreeVo assignTree = userService.getAssignTree(param);
        return ResultUtils.success("查询成功", assignTree);
    }

    @ApiOperation("修改密码")
    @PostMapping("/updatePassword")
    public ResultVo updatePassword(@RequestBody UpdatePasswordParam param) {
        User user = userService.getById(param.getUserId());
        if (!param.getOldPassword().equals(user.getPassword())) {
            return ResultUtils.error("原密码不正确！");
        }
        if(passwordEncoder.matches(param.getOldPassword(),user.getPassword())){
            return ResultUtils.error("原密码不正确！");
        }
        //更新条件
        UpdateWrapper<User> query = new UpdateWrapper<>();
        query.lambda().set(User::getPassword, passwordEncoder.encode(param.getPassword()))
                .eq(User::getUserId, param.getUserId());
        if (userService.update(query)) {
            return ResultUtils.success("密码修改成功！");
        }
        return ResultUtils.error("密码修改失败！");
    }

    @ApiOperation("退出登录")
    @PostMapping("/loginOut")
    public ResultVo loginOut(HttpServletRequest request, HttpServletResponse response){
        Authentication authentication=SecurityContextHolder.getContext().getAuthentication();
        if (authentication!=null){
            new SecurityContextLogoutHandler().logout(request,response,authentication);
        }
        return ResultUtils.success("退出登录成功！");
    }

    @ApiOperation("获取用户信息")
    @GetMapping("/getInfo")
    public ResultVo getInfo(Long userId) {
        //获取用户信息
        User user = userService.getById(userId);
        //获取用户的权限信息
        List<Menu> menuList;
        //判断是否为超级管理员
        if (StringUtils.isNotEmpty(user.getIsAdmin()) && user.getIsAdmin().equals("1")) {
            menuList = menuService.list();
        } else {
            menuList = menuService.getMenuByUserId(userId);
        }
        //过滤出code字段
        //获取菜单表的code字段
        //设置返回值
        UserInfo userInfo = new UserInfo();
        userInfo.setName(user.getNickName());
        userInfo.setUserId(user.getUserId());
        userInfo.setPermissions(Optional.ofNullable(menuList).orElse(new ArrayList<>())
                .stream()
                .filter(item -> item != null && StringUtils.isNotEmpty(item.getCode()))
                .map(Menu::getCode).toArray());
        return ResultUtils.success("查询成功", userInfo);
    }

}

